import { ElMessage, ElMessageBox } from 'element-plus'

// 内存计数id
const __objRandom = { st: 0, st1: createUUid('') }

/**
 * 产生对象级唯一ID 提高性能
 * @param key
 * @return string
 */
export function createOID(key = ''):string {
     __objRandom.st += 1
    if (__objRandom.st >= 99999999999) { __setRandomNum(0) }
    return `${key}${__objRandom.st1}_${__objRandom.st}`
}

/**
 *
 * @param st
 * @private
 */
function __setRandomNum(st:number):void {
     __objRandom.st = st
     __objRandom.st1 = createUUid('')
}


/**
 * 产生唯一ID temp 线不加uuid
 * @param key
 */
export function createUUid(key = '') {
    return key + Math.floor(Math.random() * 10000)
}

/**
 *
 * @param min
 * @param max
 * @returns {number}
 */
export function createRandom(max:number, min = 1):number {
    return Math.round(Math.random() * (max - min + 1) + min)
}

/**
 * @description:数组转对象
 * @param arr:Array<any>
 * @param att:string
 * @param value:*
 * @return {*}
 */
export function arrToMap(arr:Array<any>, att = 'id', value:any = null):any {
    const re:any = {}
    for (const item of arr) {
        re[item[att]] = value === null ? item : value
    }
    return re
}
/**
 * 数组转对象
 * @param arr
 * @param value
 */
export function arrToMap2(arr:Array<any>, value = true):any {
    const re:any = {}
    for (const item of arr) {
        re[item] = value
    }
    return re
}

/**
 * tree to map
 * @param arr
 * @param att
 * @param value
 */
export function treeToMap(arr:Array<any>, att = 'name', value = null, func:any = null) {
    const re: any = {}
    travelTree(arr, (item: any, pItem: any) => {
        if (Object.prototype.hasOwnProperty.call(item, att)) {
            if (func) re[item.name] = func(item, pItem)
            else re[item.name] = value === null ? item : value
        }
    })
    return re
}

/**
 * 属性赋值
 * @param toObj
 * @param fromObj
 * @returns {*}
 */
export function assign3(toObj:any, fromObj:any) {
    for (const att in fromObj) {
        const _value = fromObj[att]
        if (Array.isArray(_value) ||
            typeof _value !== 'object' ||
            !Object.prototype.hasOwnProperty.call(toObj, att) ||
            (Object.prototype.hasOwnProperty.call(toObj, att) &&
                (toObj[att] === null ||
                    toObj[att] === undefined ||
                    typeof toObj[att] !== 'object')) ||
            Array.isArray(toObj[att])
        ) {
            toObj[att] = _value
        } else assign3(toObj[att], _value)
    }
    return toObj
}

/**
 *
 * @param toObj
 * @param fromObj
 * @returns {*}
 */
export function assign2(toObj:any, fromObj:any):any {
    for (const att in fromObj) {
        const _value = fromObj[att]
        if (
            Array.isArray(_value) ||
            typeof _value !== 'object' ||
            !Object.prototype.hasOwnProperty.call(toObj, att) ||
            ((Object.prototype.hasOwnProperty.call(toObj, att) &&
                    (toObj[att] === null || toObj[att] === undefined || typeof toObj[att] !== 'object')) ||
                Array.isArray(toObj[att]))
        ) {
            toObj[att] = _value
        } else assign2(toObj[att], _value)
    }
    return toObj
}


/**
 *
 * @param obj
 * @param attName
 */
export function hasOwnProperty(obj:any, attName:any) {
    return Object.prototype.hasOwnProperty.call(obj, attName)
}

/**
 *
 * @param toObj
 * @param fromObj
 * @returns {*}
 */
export function copyDiyData(toObj:any, fromObj:any):any {
    for (const att in fromObj) {
        if (att.indexOf('_') !== 0) {
            const _value = fromObj[att]
            if (!_value) {
                toObj[att] = _value
            } else if (Array.isArray(_value)) {
                toObj[att] = _value.map((item:any) => {
                    return copyDiyData({}, item)
                })
            } else if (typeof _value === 'object') {
                toObj[att] = copyDiyData(toObj[att] || {}, _value)
            } else {
                toObj[att] = _value
            }
        }
    }
    return toObj
}

/**
 * 清空数组保留引用
 * @param arr
 */
export function clearArray(arr:any[]) {
    if (!arr) return
    while (arr.length > 0) {
        arr.splice(0, 1)
    }
}

/**
 *
 * @param obj
 */
export function copyObjectDeep(obj:any, type:any):any {
    if (!obj) return {}
    try {
        if (type === 1) {
            return JSON.parse(JSON.stringify(obj))
        } else {
            return obj
        }
    } catch (e: any) {
        console.trace(e.stack)
    }
    return {}
}


/**
 * 简单对象深拷贝使用
 * @param obj
 * @param errorObj
 */
export function deepCopyObject(obj:any, errorObj:any = {}):any {
    if (!obj) return {}
    try {
         return JSON.parse(JSON.stringify(obj))
    } catch (e: any) {
        console.trace(e.stack)
    }
    return errorObj
}

/**
 * 对象深拷贝使用
 * @param obj
 * @param ext 全局过滤某个属性 不论层级
 */
export function deepCloneObject(obj:any, ext = ''):any {
    if (!obj || typeof obj !== 'object') return obj
    if (Array.isArray(obj)) {
        const result:any[] = []
        for (const item of obj) {
            result.push(deepCloneObject(item))
        }
        return result
    }
    const result:any = {}
    for (const key in obj) {
        if (!ext || ext.indexOf(`'${key}'`) === -1) {
            const value = obj[key]
            result[key] = (typeof value === 'object') ? deepCloneObject(value) : value
        }
    }
    return result
}

/**
 * 一层属性赋值
 * @param toObj
 * @param obj
 */
export function copyObjectSimple(obj:any, toObj:any = {}):any {
    if (!toObj) toObj = {}
    if (!obj) return toObj
    for (const att in obj) {
        const _value = obj[att]
        if (typeof _value !== 'object') { toObj[att] = _value }
    }
    return toObj
}


/**
 * 一层属性赋值 以toObj属性为准
 * @param toObj
 * @param obj
 */
export function copyObjectSameTo(obj:any, toObj:any = {}):any {
    if (!toObj) toObj = {}
    if (!obj) return toObj
    for (const att in toObj) {
        if (Object.prototype.hasOwnProperty.call(obj, att)) { toObj[att] = obj[att] }
    }
    return toObj
}
/**
 * 一层属性赋值 以toObj属性为准
 * @param toObj
 * @param obj
 */
export function copyObjectSameFrom(obj:any, toObj:any = {}):any {
    if (!toObj) toObj = {}
    for (const att in obj) {
        if (Object.prototype.hasOwnProperty.call(toObj, att)) { toObj[att] = obj[att] }
    }
    return toObj
}


/**
 * 一层属性赋值 以toObj属性为准
 * @param obj
 * @param toObj
 * @param exp
 */
export function copyObjectSameExpTo(obj:any, toObj:any = {}, exp = ''):any {
    if (!toObj) toObj = {}
    if (!obj || typeof obj !== 'object') return toObj
    exp = `,${exp},`
    for (const att in toObj) {
        if (Object.prototype.hasOwnProperty.call(obj, att) && exp.indexOf(`,${att},`) === -1) {
            toObj[att] = obj[att]
        }
    }
    return toObj
}

/**
 * 单拆一个实体对象用
 * @param obj
 * @param toObj
 * @param exp
 */
export function copyObjectSameExpTo1(obj:any, toObj:any = {}, exp = ''):any {
    if (!toObj) toObj = {}
    if (!obj || typeof obj !== 'object') return toObj
    exp = `,${exp},`
    for (const att in toObj) {
        if (Object.prototype.hasOwnProperty.call(obj, att) && exp.indexOf(`,${att},`) === -1 && att.indexOf('_') !== 0) {
            toObj[att] = obj[att]
        }
    }
    return toObj
}

/**
 * 一层属性赋值
 * @param toObj
 * @param attList
 * @param obj
 */
export function copyObjectAttArr(obj:any, toObj:any, attList:any[]):any {
    if (!toObj) toObj = {}
    if (!obj) return toObj
    for (const att of attList) {
        if (Object.prototype.hasOwnProperty.call(obj, att)) { toObj[att] = obj[att] }
    }
    return toObj
}

/**
 * 排除属性拷贝
 * @param obj
 * @param extList
 * @param copy
 */
export function copyObjectAttExt(obj:any, extList:any[], copy = true, filter = false):any {
    if (!obj) return null
    const re:any = {}
    if (copy) { obj = (extList && extList.length > 0) ? copySimpleAttExt(obj, extList) : deepCopyObject(obj) }
    for (const att in obj) {
        if (extList.indexOf(att) === -1)re[att] = obj[att]
    }
    return re
}

/**
 * 一层属性简单拷贝
 * @param obj
 * @param extList
 */
export function copySimpleAttExt(obj:any, extList:any[]) {
    const re:any = {}
    for (const att in obj) {
        if (extList.indexOf(att) === -1)re[att] = obj[att]
    }
    return re
}


/**
 * 遍历父节点扁平化树
 * @param source
 * @param att
 */
export function createTravelParentMap (source:any, att = 'id') {
    const map = treeToMap(source, 'name', null, (item: any, pItem: any) => {
        return { data: item, item, parent: pItem }
    })
    return map
}

/**
 * 遍历树父节点 从节点往上反
 * @param source
 * @param node
 * @param nodeFunc
 * @param att
 * @param sourceMap
 */
export function travelTreeParent(source:any, node:any, nodeFunc:any, att = 'id', sourceMap:any = null) {
    const map = sourceMap || createTravelParentMap(source, att)
    travelTreeParentItem(node, map, nodeFunc, att)
}

/**
 * 遍历树父节点
 * @param node
 * @param map
 * @param itemFunc
 * @param att
 */
function travelTreeParentItem(node:any, map:any, itemFunc:any, att = 'name'):any {
    if (!hasOwnProperty(map, node[att])) return
    const parent = map[node[att]].parent
    if (!parent) return
    const flag = itemFunc(parent, node)
    if (flag === -1) return -1
    return travelTreeParentItem(parent, map, itemFunc, att)
}


/**
 * 遍历树
 * @param arr 数组或单个对象
 * @param itemFunc 处理元素的函数
 * @param child 子数组属性名 默认 children
 * @param level
 * @param pItem
 * @param parentData
 * @param pChildren
 */
export function travelTree(arr:any, itemFunc:any = null, child:any = 'children', level = 0, pItem:any = null, parentData:any = null, pChildren:any = null):any {
    if (!arr) { return }
    if (!Array.isArray(arr)) arr = [arr]
    let flag:any = 0
    let len = arr.length
    for (let i = 0; i < arr.length; i++) {
        let node = arr[i]
        if (itemFunc != null) {
            flag = itemFunc(node, pItem, level, i, parentData, pChildren)
            if (flag === -1) { return -1 } else if (flag === -2) {
                i = i - 1
                len = len - 1
                continue
            } else if (flag === -3) continue
        }
        // 支持itemFunc对元素进行替换
        node = arr[i]
        if (Object.prototype.hasOwnProperty.call(node, child) && node[child]) {
            flag = travelTree(node[child], itemFunc, child, level + 1, node, flag, arr)
            if (flag === -1) { return -1 }
        }
    }
}

/**
 *
 * @param treeData
 * @param value
 * @param att
 * @param childAtt
 */
export function getTreeItemData(treeData:any, value:any, att = 'id', childAtt = 'children'):any {
    let re:any = null
    travelTree(treeData, (item:any) => {
        if (Object.prototype.hasOwnProperty.call(item, att) && item[att] === value) {
            re = item
            return -1
        }
    }, childAtt)
    return re
}


/**
 * 列表转换为树结构
 * @param arr  转换列表
 * @param itemFunc 元素处理 void ( item ,parentItem)
 * @param id 唯一标识
 * @param pid 父亲唯一标识
 * @param child 存放子的数组属性名
 * @returns {Array} 返回树结构
 */
export function listToTree(arr:Array<any>, itemFunc:any = null, id = 'id', pid = 'parentId', child = 'children') {
    const map:any = {}
    const re:Array<any> = []
    for (const item of arr) {
        map[item[id]] = item
        item[child] = []
    }
    for (const item of arr) {
        if (Object.prototype.hasOwnProperty.call(map, item[pid])) {
            if (itemFunc) { itemFunc(item, map[item[pid]]) }
            map[item[pid]][child].push(item)
        } else {
            if (itemFunc) { itemFunc(item, null) }
            re.push(item)
        }
    }
    return re
}

/**
 * 列表转换为树结构
 * @param arr
 * @param value
 * @param key
 * @param child
 */
export function getTreeItem(arr:Array<any>, value:any, key = 'id', child = 'children'):any {
    let re = null
    travelTree(arr, (item:any) => {
        if (item && Object.prototype.hasOwnProperty.call(item, key) && item[key] === value) {
            re = item
            return -1
        }
    }, child)
    return re
}

/**
 * 信息提示框
 * @param msg
 * @param type success/warning/info/error
 * @param duration number
 */
export function popMessage(msg:string, type:any = 'success', duration:any = null) {
    const opt:any = {
        showClose: true,
        message: msg,
        type
    }
    if (duration) { opt.duration = duration }
    ElMessage(opt)
}

/**
 *
 * @param start
 * @param end
 * @param func
 */
export function createNumberArr(end:number, start = 0, func:any = null):any[] {
    const re: any[] = []
    for (let i = start; i < end; i++) {
        re.push(func ? func(i) : { value: i })
    }
    return re
}

/**
 *
 * @param msg
 * @param ok
 * @param cancel
 * @param title
 * @param okLabel
 * @param cancelLabel
 * success，error，info和 warning
 */
export function popAskWin(msg:string, result:any, cancel:any = null, title = '', okLabel = '确定', cancelLabel = '取消', type = 'info') {
    ElMessageBox.confirm(msg, title, {
        confirmButtonText: okLabel,
        cancelButtonText: cancelLabel,
        autofocus: false
    }).then(() => {
        if (result)result()
    }).catch(() => {
        if (cancel)cancel()
    })
}

/**
 * 消息询问
 * @param msg
 * @param title
 * @param okLabel
 * @param cancelLabel
 * @param type
 */
export function popAskWin2(msg:string, title = '', okLabel = '确定', cancelLabel = '取消', type = 'info'):Promise<void> {
    return new Promise((resolve, reject) => {
        popAskWin(msg, () => {
            resolve()
        }, () => {
            reject(new Error(''))
        }, title, okLabel, cancelLabel, type)
    })
}

/**
 * 消息窗口
 * @param msg
 * @param result
 * @param title
 * @param okLabel
 * @param type
 */
export function popInfoWin(msg:string, result:any = null, title = '', okLabel = '确定') {
    ElMessageBox.alert(msg, title, {
        confirmButtonText: okLabel,
        callback: () => {
            if (result !== null) { result() }
        }
    })
}


/**
 * 延时处理
 * @param result
 */
export function callLater(result:any, dur = 0) {
    const cid = setTimeout(() => {
        clearTimeout(cid)
        result()
    }, dur)
    return cid
}

/**
 * 从数组删除某个值的数据
 * @param arr
 * @param value
 * @param att
 */
export function removeItemFromArr(arr:Array<any>, value:any, att:any = 'id'):any {
    if (!arr || !Array.isArray(arr)) { return null }
    for (let i = 0; i < arr.length; i++) {
        const item = arr[i]
        if (item && Object.prototype.hasOwnProperty.call(item, att) && item[att] === value) {
            arr.splice(i, 1)
            return item
        }
    }
    return null
}

/**
 * 根据下标删除对象 并返回下标
 * @param arr
 * @param item
 * @return number
 */
export function removeArrayItem(arr:Array<any>, item:any):any {
    const index = arr.indexOf(item)
    if (index > -1) arr.splice(index, 1)
    return index
}

/**
 * 获得匹配条件数据
 * @param arr
 * @param value
 * @param att
 * @returns {*}
 */
export function getSelectItem(arr:any[], value:any, att:any = 'selected') {
    if (!arr || !Array.isArray(arr)) { return null }
    for (const item of arr) {
        if (item && Object.prototype.hasOwnProperty.call(item, att) && item[att] === value) { return item }
    }
    return null
}

/**
 * 获得匹配条件数据
 * @param arr
 * @param value
 * @param att
 * @returns {{index,item}}
 */
export function getSelectItemData(arr:any[], value:any, att:any = 'selected') {
    if (!arr || !Array.isArray(arr)) { return { index: -1, data: null } }
    const len = arr.length
    for (let i = 0; i < len; i++) {
        const item = arr[i]
        if (item && Object.prototype.hasOwnProperty.call(item, att) && item[att] === value) return { index: i, data: item }
    }
    return { index: -1, data: null }
}

/**
 * 删除 匹配条件数据
 * @param arr
 * @param value
 * @param att
 * @returns {{index,item}}
 */
export function deleteSelectItem(arr:any[], value:any, att:any = 'id') {
   const { index, data } = getSelectItemData(arr, value, att)
    if (index !== -1)arr.splice(index, 1)
    return data
}


/**
 * 强制转换 json string
 * @param value
 * @param def
 */
export function jsonString(value:any, def = ''):string {
    let re = def
    try {
       if (value) re = JSON.stringify(value)
    } catch (e) {
    }
    return re
}

/**
 * 字符转对象
 * @param value
 * @param def
 */
export function jsonObject(value:string, def:any|null = null):any {
    let re = def
    try {
       if (value) re = JSON.parse(value)
    } catch (e) {
    }
    return re
}

/**
 * 参数处理
 * @param {*} params  参数
 */
export function tansParams(params: any) {
    let result = ''
    for (const propName of Object.keys(params)) {
        const value = params[propName]
        const part = encodeURIComponent(propName) + '='
        if (value !== null && typeof value !== 'undefined') {
            // if(Array.isArray(value)){
            //   for(let key of value){
            //     result += '&'+part + encodeURIComponent(key)  ;
            //   }
            // }
            if (typeof value === 'object') {
                for (const key of Object.keys(value)) {
                    if (value[key] !== null && typeof value[key] !== 'undefined') {
                        const params = propName + '[' + key + ']'
                        const subPart = encodeURIComponent(params) + '='
                        result += subPart + encodeURIComponent(value[key]) + '&'
                    }
                }
            } else {
                result += part + encodeURIComponent(value) + '&'
            }
        }
    }
    return result
}

/**
 *
 * @param name
 */
export function getUrlParams(name:string):any {
    const re = window.location.search.substring(1).match(new RegExp('(^|&)' + name + '=([^&]*)(&|$)'))
    return re ? decodeURIComponent(re[2]) : null
}

/**
 * 平移不处理
 */
export function getRequest():any {
    const result = {}
    const query = window.location.href.split('?')[1]
    if (query) {
        const queryArr = query.split('&')
        queryArr.forEach((item) => {
            const value = item.split('=')[1]
            const key = item.split('=')[0]
            const results = result as any
            results[key] = value
        })
    }
    return result
}

/**
 *
 * @param title
 */
export function setDocumentTitle(title:string) {
    document.title = title
}


/**
 * 读取文件的 dataUrl
 * @param file
 */
export function getFileExt(name:string) {
    const index = name.lastIndexOf('.')
    if (index >= 0 && index < name.length - 1) return name.substring(index + 1, name.length).toLocaleLowerCase()
    return ''
}
/**
 * 读取文件的 dataUrl
 * @param file
 */
export function getFileName(name:string) {
    const index = name.lastIndexOf('.')
    return index === -1 ? name : name.substring(0, index)
}

/**
 *
 * @param name
 * @param url
 */
export function getLocalParam(name:string, url = '') {
    if (!url) url = window.location.href
    const index = url.indexOf('?')
    if (index === -1) return null
    url = url.substring(index, url.length)
    if (url.lastIndexOf('#') > -1 && url.lastIndexOf('?') < url.lastIndexOf('#')) {
        console.log(url.lastIndexOf('#'))
        url = url.substring(0, url.lastIndexOf('#'))
    }
    const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
    const r = url.substring(1).match(reg)
    if (r != null) return encodeURIComponent(r[2])
    return null
}


/**
 * 设置url参数
 * @param name
 * @param value
 * @param url
 */
export function setLocalParam(name:string, value:any, url = '') {
    if (!url || url.indexOf('?') === -1) return url
    const arr = url.split('?')
    const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
    let query = arr[1]
    const r = query.match(reg)
    if (r != null) {
        query = query.replace(r[0], r[1] + name + '=' + value + r[3])
    }
    return arr[0] + '?' + query
}


/**
 * 格式化日期
 * @param date
 * @param fmt
 * @returns {*}
 */
export function dateFormatStr(date:Date, fmt = 'yyyy-MM-dd HH:mm:ss'):string {
    const o:any = {
        'M+': date.getMonth() + 1,
        'd+': date.getDate(),
        'H+': date.getHours(),
        'm+': date.getMinutes(),
        's+': date.getSeconds(),
        'S+': date.getMilliseconds()
    }
    if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(RegExp.$1, (String(date.getFullYear())).substr(4 - RegExp.$1.length))
    }
    for (const k in o) {
        if (new RegExp('(' + k + ')').test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(String(o[k]).length)))
        }
    }
    return fmt
}

/**
 *
 * @param innerStr
 */
export function createDom(innerStr:string):any {
   const dom = document.createElement('div')
    dom.innerHTML = innerStr
    return dom.children[0]
}

/**
 * 图片转文件
 * @param dataUrl
 * @param fileName
 */
export function dataUrlToFile(dataUrl:string, fileName = '') {
    const arr:any[] = dataUrl.split(',')
    const mime = arr[0].match(/:(.*?);/)[1]
    const batStr = atob(arr[1]); let n = batStr.length; const u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = batStr.charCodeAt(n)
    }
    return new File([u8arr], fileName, { type: mime })
}


/**
 * 弹出窗口内部排除项确认
 */
const popValidClass:string [] = ['el-select', 'el-input', 'el-tree']
export function validIsInElement(node:any, classParent = ''):boolean {
    if (!node || !node.parentNode || node.tagName.toLocaleLowerCase() === 'body') return false
    const className = node.getAttribute('class')
    if (className) {
        if (classParent && className.indexOf(classParent) > -1) return true
        for (const cl of popValidClass) {
            if (className.indexOf(cl) > -1) return true
        }
    }
    return validIsInElement(node.parentNode)
}

// 对象转字符串&拼接
export function pars(param:any, key:any, encode:any):string {
    if (param == null) return ''
    const arr = []
    const t = typeof (param)
    if (t === 'string' || t === 'number' || t === 'boolean') {
        arr.push(key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param))
    } else {
        for (const i in param) {
            const k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i)
            arr.push(pars(param[i], k, encode))
        }
    }
    return arr.join('&')
}

// 清除newPid
export function clearNewPid(arr:any) {
    for (let i = 0; i < arr.length; i++) {
        if (arr[i].newPid) {
            arr[i].newPid = 0
        }
        if (arr[i].children.length > 0) {
            clearNewPid(arr[i].children)
        }
    }
}

// 添加newPid
export function addNewPid(arr:any, data:any) {
    for (let i = 0; i < arr.length; i++) {
        if (arr[i].type !== 'SCREEN') {
            arr[i].newPid = data
        }
        if (arr[i].newPid && arr[i].newPid.type === 'SCREEN') {
            arr[i].newPid = 0
        }
        if (arr[i].children && arr[i].children.length > 0) {
            addNewPid(arr[i].children, arr[i])
        }
    }
}

// ###################################################################### test ################################################
const _catchObj = {
    logCatchTempTime: 0
}

/**
 *
 * @param start
 * @param key
 */
export function showTimeLog(key = '<<----------------------------time log', start = false) {
    const time = new Date().getTime()
    if (start) {
        _catchObj.logCatchTempTime = time
        console.log('start-->0', key)
    } else {
        console.log(time - _catchObj.logCatchTempTime, key)
        _catchObj.logCatchTempTime = time
    }
}

/**
 *
 * @param func
 * @param dur
 */
export function useBound(func:any, dur = 60) {
    let catchData:any = null
    let isWait = false
    let cid:any = null
    const result:any = func
    const push = (data:any) => {
        catchData = data
        if (isWait) return
        isWait = true
        cid = callLater(() => {
            isWait = false
            result(catchData)
        }, dur)
    }
    const reset = () => {
        catchData = null
        isWait = false
        if (cid)clearTimeout(cid)
    }
    return {
        push,
        reset
    }
}

